package br.unifor.cct.mia.evaluate;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;

import br.unifor.cct.mia.dataenhancement.Database;
import br.unifor.cct.mia.dataenhancement.DatabaseUtil;
import br.unifor.cct.mia.dataenhancement.Structure;
import br.unifor.cct.mia.evaluate.classification.WekaClassification;
import br.unifor.cct.mia.evolutionary.Genotype;
import br.unifor.cct.mia.ga.Ga;
import br.unifor.cct.mia.util.Methods;
import br.unifor.cct.mia.util.SaveReportFSW;

public class WekaFSWEvaluate implements Evaluate {
	
	private Map genesAnt;
	private Structure structure;
	private Database database;
	private Ga ga;
	private String[] options;
	
	public double cost(Genotype gen, int strucSize) {		
		double sum = 0;
		
		Integer hashCode = new Integer(gen.hashCode());
		if (!genesAnt.containsKey(hashCode)) {			
			
			try {
				SaveReportFSW report = new SaveReportFSW("temp/result.txt",gen,strucSize,structure.getStrucFile());
				
				int lineIndex = 0;
				String line = DatabaseUtil.readLine(database.getDbFile(),lineIndex);
				while ( line != null  ) {
					String cols[] = line.split(",");
					String finalLine = "";
					ArrayList occuredCols = new ArrayList();
					
					for ( int i=1; i<strucSize; i++ ) {
						if ( Methods.arrayContains(gen.getGene(),i) &&
								!occuredCols.contains(new Double(i)) ) {
							occuredCols.add(new Double(i));
							finalLine += cols[(int)i-1] + ",";
						}						
					}
					finalLine += cols[strucSize-1];
					report.addLine(finalLine);
					
					lineIndex++;
					line = DatabaseUtil.readLine(database.getDbFile(),lineIndex);
				}				
				
				report.saveToDisk();
				
				File f = report.getFile();
				
				WekaClassification classificator = new WekaClassification(ga.getLearnerType(),options);
				sum = classificator.evaluate(f);	
				
			} catch (IOException e1) {
				e1.printStackTrace();				
			} catch (InterruptedException e) {
				e.printStackTrace();
			}			
			
			genesAnt.put(hashCode, new Double(sum));
		}
		else {
			sum = ((Double)genesAnt.get(hashCode)).doubleValue();
		}
		
		return sum;
	}
	
	public Object evaluate(Object value,String[] options) {
		this.options = options;           
		Object[] o = (Object[]) value;
		structure = (Structure) o[0];
		genesAnt = (Map) o[1];
		database = (Database) o[2];
		ga = (Ga)o[3];
		
		ga.sum = 0;
		ga.indexBestWorst[0] = ga.indexBestWorst[1] = 0;
		
		for(int i = 0; i < ga.configurations.getPopsize(); i++) {        	
			ga.population[i].setFitness(cost((Genotype)ga.population[i],structure.size()));                    	
			if (ga.population[i].getFitness() > ga.population[ga.indexBestWorst[0]].getFitness()) 
				ga.indexBestWorst[0] = i;
			else 
				if (ga.population[i].getFitness() < ga.population[ga.indexBestWorst[1]].getFitness()) 
					ga.indexBestWorst[1] = i;
			
			ga.sum += ga.population[i].getFitness();
		}
		
		return ga.population;
	}
	
}
